Imports System.IO
Imports System.Windows.Media.Animation
Imports System.Windows.Threading


' The main screensaver window.
Partial Public Class MainWindow
    Inherits System.Windows.Window

    ' Mouse position is tracked to determine when the screensaver should close.
    Dim _lastKnownMousePos As Point
    ' Timer used determine when to display the next picutre.
    Dim _refreshTimer As DispatcherTimer
    ' The RSS feed list to use.
    Dim _feedList As FeedList = Nothing

    Public Sub New()
        InitializeComponent()

        Me._lastKnownMousePos.X = -1
        Me._lastKnownMousePos.Y = -1

        AddHandler MouseMove, AddressOf MainWindow_MouseMove
        AddHandler MouseDown, AddressOf MainWindow_MouseDown
        AddHandler KeyDown, AddressOf MainWindow_KeyDown
    End Sub

    ' Setup the screensaver after this window is loaded.
    Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)

        ' Using the IsVisibleChanged event as a trigger to determine when to
        ' start the storyboard animation for the text area of the screensaver.
        AddHandler textArea.IsVisibleChanged, AddressOf textArea_IsVisibleChanged

        ' Initialize and load the feed list.
        Try
            Me._feedList = New FeedList()
            Me._feedList.Load()
        Catch e1 As FileNotFoundException
            Dim msg As String = ResourcesWrapper.FeedsInteropErrorText

            MessageBox.Show(msg, ResourcesWrapper.FeedsLoadErrorText, MessageBoxButton.OK, MessageBoxImage.Error)

            Close()
            Return
        End Try

        DisplayCurrentImage()

        ' Start the timer using the value provided by the settings.
        Me._refreshTimer = New DispatcherTimer(DispatcherPriority.Normal)
        Me._refreshTimer.Interval = New TimeSpan(0, 0, SettingsWrapper.FadePauseInterval)
        AddHandler _refreshTimer.Tick, AddressOf _refreshTimer_Tick
        Me._refreshTimer.Start()
    End Sub


    Private Sub textArea_IsVisibleChanged(ByVal sender As Object, ByVal e As DependencyPropertyChangedEventArgs)
        ' Determine visibility (true or false).
        Dim visible As String = e.NewValue.ToString()

        If visible = Boolean.TrueString Then
            ' Start storyboard when visibility goes from false to true.
            BeginTextAreaStoryboard()
        End If
    End Sub


    Private Sub _refreshTimer_Tick(ByVal sender As Object, ByVal e As EventArgs)
        ' Hide text area before displaying new image.
        textArea.Visibility = Visibility.Hidden
        Me._refreshTimer.IsEnabled = False

        ' Show next image.
        Me._feedList.MoveNext()
        DisplayCurrentImage()

        Me._refreshTimer.IsEnabled = True
    End Sub

    ' Displays the current image (and text description).
    Private Sub DisplayCurrentImage()
        Dim imageLoc As Uri = New Uri(Me._feedList.CurrentItem.Enclosure.FullName)
        Dim textDesc As String = Me._feedList.CurrentItem.Title

        DisplayImage(imageLoc)
        DisplayText(textDesc)

        textArea.Visibility = Visibility.Visible
    End Sub

    Private Sub DisplayImage(ByVal imgUri As Uri)
        If imgUri Is Nothing Then
            Throw New ArgumentNullException("uri")
        End If

        ' Use the actual width of this window minus a small
        ' amount of buffer area around the image when displaying.
        Dim w As Double = Me.ActualWidth - 25
        Dim h As Double = Me.ActualHeight - 25

        drawCanvas.Width = w
        drawCanvas.Height = h
        picContainer.Width = w
        picContainer.Height = h

        ' The default RSS text (see Resources) contains two default image references,
        ' arbitrarily called @SSaverBackground1 and @SSaverBackground2.
        If imgUri.AbsolutePath.Contains("@SSaverBackground1") Then
            ' WPF applications use the Pack URI Scheme to identify data resources.
            imgUri = New Uri("pack://application:,,/Resources/SSaverBackground1.jpg")
        ElseIf imgUri.AbsolutePath.Contains("@SSaverBackground2") Then
            imgUri = New Uri("pack://application:,,/Resources/SSaverBackground2.jpg")
        End If

        ' Create a BitmapImage instance.
        Dim bitmap As BitmapImage = Nothing
        Try
            bitmap = New BitmapImage(imgUri)
        Catch e1 As Exception
            bitmap = New BitmapImage()
        End Try

        ' Assign the new BitmapImage instance to the 'pic' element.
        pic.Source = bitmap
    End Sub

    Private Sub DisplayText(ByVal textDesc As String)
        If textDesc Is Nothing Then
            Throw New ArgumentNullException("textDesc")
        End If

        textAreaText.Text = textDesc
    End Sub

    Private Sub BeginTextAreaStoryboard()
        ' Create animation to go from value 0.0 to 1.0 over the configured interval.
        Dim anim As DoubleAnimation = New DoubleAnimation(0, 1, New Duration(New TimeSpan(0, 0, SettingsWrapper.FadePauseInterval)), FillBehavior.HoldEnd)

        ' Animate the text area of the screensaver and affect its opacity.
        Storyboard.SetTargetName(anim, "textArea")
        Storyboard.SetTargetProperty(anim, New PropertyPath(Canvas.OpacityProperty))

        ' Create and start the storyboard containing the animation.
        Dim fadeIn As Storyboard = New Storyboard()
        fadeIn.Children.Add(anim)

        textArea.BeginStoryboard(fadeIn)
    End Sub

    Private Sub MainWindow_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
        ' Acquire current position.
        Dim currPos As Point = e.GetPosition(Me)

        ' Determine if mouse movement warrants closing the screensaver.
        If Me._lastKnownMousePos.X = -1 AndAlso Me._lastKnownMousePos.Y = -1 Then
            ' Ignore the case when this event handler is first fired.
            Me._lastKnownMousePos = currPos
        Else
            ' If the mouse has moved significantly since first call, close the app.
            If (Math.Abs(currPos.X - Me._lastKnownMousePos.X) > 50) OrElse (Math.Abs(currPos.Y - Me._lastKnownMousePos.Y) > 50) Then
                Me.Close()
            End If
        End If
    End Sub

    Private Sub MainWindow_MouseDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
        Me.Close()
    End Sub

    Private Sub MainWindow_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
        Me.Close()
    End Sub

End Class
